---
title: 读写HDFS Parquet数据
---

<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
-->

使用PXF HDFS连接器读写Parquet格式数据。本节介绍如何读写以Parquet格式存储的HDFS文件，包括如何创建、查询和写入引用HDFS文件的外部表。

PXF当前仅支持读写基本Parquet数据类型。

<div class="note">PXF Parquet写入支持是一个Beta功能。</div>


## <a id="prereq"></a>先决条件

在尝试从HDFS读取或向HDFS写入数据之前，请确保已满足PXF Hadoop[先决条件](access_hdfs.html#hadoop_prereq)。


## <a id="datatype_map"></a>数据类型映射

要在Greenplum数据库中读写Parquet基本数据类型，请将Parquet数据值映射到相同类型的Greenplum数据库列。下表总结了外部映射规则：

<a id="p2g_type_mapping_table"></a>

| Parquet数据类型| PXF/Greenplum数据类型|
|-------------------|-------------------------|
| boolean | Boolean |
| byte_array | Bytea, Text |
| double | Float8 |
| fixed\_len\_byte\_array | Numeric |
| float | Real |
| int\_8, int\_16 | Smallint, Integer |
| int64 | Bigint |
| int96 | Timestamp |

**注意**：当写入Parquet时，PXF会将`timestamp`本地化为当前系统时区，并将其转换为通用时间(UT)，最终转换为`int96`。


## <a id="profile_cet"></a>创建外部表

PXF HDFS连接器`hdfs:parquet`配置文件支持读写Parquet格式的HDFS数据。当您将记录插入可写外部表中时，您插入的数据块将写入指定目录中一个或多个文件。

使用以下语法创建引用HDFS目录的Greenplum数据库外部表：

``` sql
CREATE [WRITABLE] EXTERNAL TABLE <table_name>
    ( <column_name> <data_type> [, ...] | LIKE <other_table> )
LOCATION ('pxf://<path-to-hdfs-dir>
    ?PROFILE=hdfs:parquet[&<custom-option>=<value>[...]]')
FORMAT 'CUSTOM' (FORMATTER='pxfwritable_import'|'pxfwritable_export');
[DISTRIBUTED BY (<column_name> [, ... ] ) | DISTRIBUTED RANDOMLY];
```

[CREATE EXTERNAL TABLE](../ref_guide/sql_commands/CREATE_EXTERNAL_TABLE.html)命令中使用的特定关键字和值见下表中描述。

| 关键字| 值|
|-------|-------------------------------------|
| \<path&#8209;to&#8209;hdfs&#8209;file\>    | HDFS数据存储中目录或文件的绝对路径 |
| PROFILE    | `PROFILE`关键字必须指定为`hdfs:parquet`|
| \<custom&#8209;option\>=\<value\>  | \<custom-option\>描述见下方|
| FORMAT 'CUSTOM' | 使用`FORMAT` '`CUSTOM`'时指定`(FORMATTER='pxfwritable_export')` (写入) 或 `(FORMATTER='pxfwritable_import')` (读取). |
| DISTRIBUTED BY    | 如果您计划将现有Greenplum数据库表中的数据加载到可写外部表，考虑在可写外部表上使用与Greenplum表相同的分布策略或\<字段名\>。 这样做可以避免数据加载操作中segment节点间额外的数据移动。 |

<a id="customopts"></a>
PXF `hdfs:parquet` 配置文件支持与编码和压缩有关的写入选项。您可以在`CREATE WRITABLE EXTERNAL TABLE` `LOCATION`子句中指定这些写入选项。`hdfs:parquet`配置文件支持以下自定义选项：

| 写入选项| 值描述|
|-------|-------------------------------------|
| COMPRESSION_CODEC    | 压缩编码器别名。 用于写入Parquet数据受支持的压缩编码器包括： `snappy`, `gzip`, `lzo`, 和`uncompressed`。 如果未提供此选项，PXF将使用`snappy`压缩编码器来压缩数据。 |
| ROWGROUP_SIZE | Parquet文件由一个或多个行组组成，将数据逻辑划分为行。`ROWGROUP_SIZE` 标识行组的大小(以字节为单位)。默认的行组大小为`8 * 1024 * 1024`字节。|
| PAGE_SIZE | 行组由划分为页面的列块组成。`PAGE_SIZE`是此类页面的大小(以字节为单位)。默认的页面大小为`1024 * 1024`字节。|
| DICTIONARY_PAGE_SIZE | 当PXF写入Parquet文件时，默认情况下启用字典编码。每列、每行组只有一个字典页面。`DICTIONARY_PAGE_SIZE`与`PAGE_SIZE`类似，但是对于字典而言：默认字典页面大小为`512 * 1024`字节。 |
| PARQUET_VERSION | Parquet版本；支持`v1` 和 `v2`。默认的Parquet版本为`v1`。|

**注意**: 如果您不希望PXF压缩数据，则必须明确指定`uncompressed`。

使用PXF写入HDFS的Parquet文件具有以下命名格式：`<file>.<compress_extension>.parquet`，例如 `1547061635-0000004417_0.gz.parquet`.

## <a id="parquet_write"></a> 示例

本示例采用在[示例：读取HDFS中的文本数据](hdfs_text.html#profile_text_query)中介绍的数据模式。

| 列名  | 数据类型|
|-------|-------------------------------------|
| location | text |
| month | text |
| number\_of\_orders | int |
| total\_sales | float8 |

在此示例中，您将创建一个Parquet格式的可写外部表，该表引用了HDFS中的Parquet格式数据，将一些数据插入表中，然后创建一个可读外部表以读取数据。

1. 使用`hdfs:parquet`配置文件创建一个可写外部表。例如：

    ``` sql
    postgres=# CREATE WRITABLE EXTERNAL TABLE pxf_tbl_parquet (location text, month text, number_of_orders int, total_sales double precision)
        LOCATION ('pxf://data/pxf_examples/pxf_parquet?PROFILE=hdfs:parquet')
      FORMAT 'CUSTOM' (FORMATTER='pxfwritable_export');
    ```

2. 通过直接写入`pxf_tbl_parquet`表将一些记录写入HDFS的`pxf_parquet`目录中。例如：

    ``` sql
    postgres=# INSERT INTO pxf_tbl_parquet VALUES ( 'Frankfurt', 'Mar', 777, 3956.98 );
    postgres=# INSERT INTO pxf_tbl_parquet VALUES ( 'Cleveland', 'Oct', 3812, 96645.37 );
    ```

3. 回想一下，Greenplum 数据库不支持直接查询一个可写外部表。要读取`pxf_parquet`中的数据，请创建一个引用此HDFS目录的可读外部表：

    ``` sql
    postgres=# CREATE EXTERNAL TABLE read_pxf_parquet(location text, month text, number_of_orders int, total_sales double precision)
        LOCATION ('pxf://data/pxf_examples/pxf_parquet?PROFILE=hdfs:parquet')
        FORMAT 'CUSTOM' (FORMATTER='pxfwritable_import');
    ```

4. 查询可读外部表`read_pxf_parquet`：

    ``` sql
    postgres=# SELECT * FROM read_pxf_parquet ORDER BY total_sales;
    ```

    ``` pre
     location  | month | number_of_orders | total_sales
    -----------+-------+------------------+-------------
     Frankfurt | Mar   |              777 |     3956.98
     Cleveland | Oct   |             3812 |     96645.4
    (2 rows)
    ```

